
import thread
import threading
import types

ttt = None;

def synchronized_with_attr(lock_name):
    
    def decorator(method):

        def synced_method(self, *args, **kws):
            global ttt
            ttt = self
            lock = getattr(self, lock_name)
            with lock:
                return method(self, *args, **kws)
                
        return synced_method
		
    return decorator

    
def syncronized_with(lock):
	
    def synchronized_obj(obj):
		
        if type(obj) is types.FunctionType:
            
            obj.__lock__ = lock
			
            def func(*args, **kws):
                with lock:
                    obj(*args, **kws)
            return func
			
        elif type(obj) is types.ClassType:
            
            orig_init = obj.__init__
            def __init__(self, *args, **kws):
                self.__lock__ = lock
                orig_init(self, *args, **kws)
            obj.__init__ = __init__
            
            for key in obj.__dict__:
                val = obj.__dict__[key]
                if type(val) is types.FunctionType:
                    decorator = syncronized_with(lock)
                    obj.__dict__[key] = decorator(val)
            
            return obj
	
    return synchronized_obj
	
	
def synchronized(item):
	
    if type(item) is types.StringType:
        decorator = synchronized_with_attr(item)
        print "A"
        return decorator
    
    if type(item) is thread.LockType:
        decorator = syncronized_with(item)
        return decorator
		
    else:
        new_lock = threading.Lock()
        decorator = syncronized_with(new_lock)
        print "C"
        return decorator(item)


##@synchronized
##class Counter:
##	
##    def __init__(self):
##        self.counter = 0
##		
##    def add_one(self):
##        val = self.counter
##        val += 1
##        time.sleep(0.1)
##        self.counter = val
##		
##    def add_two(self):
##        val = self.counter
##        val += 2
##        time.sleep(0.1)
##        self.counter = val



class Counter:
	
    def __init__(self):
        self.counter = 0
        self.lock = threading.RLock()

    @synchronized("lock")
    def add_one(self):
        val = self.counter
        val += 1
        time.sleep(0.1)
        self.counter = val

##    @synchronized("lock")		
    def add_two(self):
        val = self.counter
        val += 2
        time.sleep(0.1)
        self.counter = val	
		
##my_counter = Counter()
##
##def class_counter1():
##    global my_counter
##    for i in range(0,10): my_counter.add_one()
##	
##def class_counter2():
##    global my_counter
##    for i in range(0,10): my_counter.add_two()
##
##thread1 = threading.Thread(target = class_counter1)
##thread2 = threading.Thread(target = class_counter2)
##
##thread1.start()
##thread2.start()
##
##thread1.join()
##thread2.join()
##
##print my_counter.counter


import time

import Queue

def f(mycallback, i):
    if (i==3):
        time.sleep(3)
    time.sleep(3)
    mycallback(i * 3)
    return i * 3

def testProcess():
    import multiprocessing as m
    p = m.Pool()
    #q = Queue.Queue()
    q = m.Queue(10)
    def callb(res):
        print res
        q.put(res)
    t = p.map_async(lambda e:f(callb, e), [1,2,3], callback=callb)
    p = m.Process()
    
    print t


def fun():
    import time
    time.sleep(10)
    print "ends"

def testThreading():
    fun()
    import threading
    a = threading.Thread(target=fun)
    #a.start()
    a.setDaemon(True)
    a.start()
    print "Hi"

if __name__ == "__main__":
    testThreading()


    
